package ngat.oss;

import ngat.message.OSS.*;
import ngat.util.logging.*;
import ngat.phase2.*; 
import ngat.instrument.*;
import ngat.phase2.nonpersist.*;

import java.io.*;
import java.util.*;

import jyd.dbms.*;
import jyd.storable.*;
import jyd.collection.*;
/**
 * Action: Adds a Source to the specified Proposal. If the replace option
 * is set and a Source of the same name exists it will be replaced with the new one.
 * Any uncompleted observations which refer to this Source will be relinked to the 
 * new Source. If there are any completed observations (i.e. NOT those which are
 * within repeating Groups)
 * @author S.N.Fraser
 * $Id: ADD_SOURCEImpl.java,v 1.1 2006/11/27 08:45:00 snf Exp $
 */
public class ADD_SOURCEImpl extends TransactionImpl {

    /** The path used to locate the Proposal in the OSS database. */
    protected Path proposalPath;
 
    /** The Source to add.*/
    protected Source source;

    /** True if the Source should be replaced (if it already exists).*/
    protected boolean replace;
    
    /** Create an ADD_SOURCEImpl from an ADD_SOURCE command.*/
    public ADD_SOURCEImpl(ADD_SOURCE request) {
	super(request);
	this.proposalPath = request.getProposalPath();
	this.source       = request.getSource();
	this.replace      = request.getReplace();
    }
       
    /**
     * Add the Source.
     * @return Boolean description of operation or an OSS_Error.
     */
    public TRANSACTION_DONE exec() {
	
	Logger logger = LogManager.getLogger("TRACE");
	
	Transaction t = null;
	try {
	    t = Transaction.current();
	    
	    // Fetch the Proposal.
	    Proposal proposal = null;
	    
	    try {
		proposal = OSS_Utilities.fetchProposal(proposalPath);
	    } catch (IOException iox) {
		logger.log(1, CLASS, id, "exec",
			   "Proposal: "+proposalPath.toString()+
			   " Error fetching from Database: "+iox);
		iox.printStackTrace();
		return error(TRANSACTION.DATABASE_READ_ERROR,			   
			     "Proposal: "+proposalPath.toString()+
			     " Error reading from database",
			     iox);
	    }		
	    
	    // If its not there fail.
	    if (proposal == null) {
		logger.log(1, "ADD_GROUP_Impl", id, "exec",
			   "Proposal: "+proposalPath.toString()+" Not in database.");
		return error(TRANSACTION.PATH_RESOLUTION_ERROR, 
			     "Could not find Proposal: "+proposalPath.toString());
	    }
	    
	    // Check if Proposal locked.
	    if (proposal.isLocked() && !(proposal.getLastEditor().equals("RCS"))) {
		//#### maybe this should be an ILLEGAL_DB_ACCESS ?
		return error(TRANSACTION.ILLEGAL_DATABASE_ACCESS, 
			     "Proposal ["+proposalPath.toString()+
			     "] is locked at this time by user ["+proposal.getLastEditor()+
			     "]- try again later");
	    }
	    
	    if (replace) {
		// Replace existing Source.

		// Check the Source is already contained in Proposal.
		if (proposal.findSource(source.getName()) == null) {
		    return error(TRANSACTION.PATH_RESOLUTION_ERROR, 
				 "Proposal ["+proposalPath.toString()+
				 "] does not contain Source ["+source.getName());
		}
		
		// Check if any Groups for which obs have link to this source
		// are currently locked and record the obs.
		
		Group       group = null;
		Observation obs   = null;
		
		List obslist = new Vector();

		Iterator igroup = proposal.listAllGroups();
		while (igroup.hasNext()) {
		    group = (Group)igroup.next();
		    
		    Iterator iobs = group.listAllObservations();
		    while (iobs.hasNext()) {
			obs = (Observation)iobs.next();
			
			if (obs.getSource() != null &&
			    obs.getSource().getName().equals(source.getName())) {
			    
			    // Check Group not locked.
			    //if (group.isLocked()) {
			    //return error(TRANSACTION.ILLEGAL_DATABASE_ACCESS, 
			    //	     "Group ["+group.getFullPath()+
			    //	     "] is locked at this time - try again later");
			    //}
			    
			    // Note the observation.
			    obslist.add(obs.getFullPath());
			    
			}
		    }
		}
		
		// Remove the old Source and replace with new one.
		Source oldSource = proposal.findSource(source.getName());
		proposal.deleteSource(oldSource);
		
		proposal.addSource(source);
		
		// Re-link any obs.
		igroup = proposal.listAllGroups();
		while (igroup.hasNext()) {
		    group = (Group)igroup.next();
		    
		    Iterator iobs = group.listAllObservations();
		    while (iobs.hasNext()) {
			obs = (Observation)iobs.next();
			
			if (obslist.contains(obs.getFullPath()))
			    obs.setSource(source);
			
		    }
		}
		
	    } else {
		// Add a new Source.
		
		// Check the Source is not already contained in Proposal.
		if (proposal.findSource(source.getName()) != null) {
		    return error(ADD_SOURCE.SOURCE_ALREADY_DEFINED, 
				 "Proposal ["+proposalPath.toString()+
				 "] already contains Source ["+source.getName());
		}
		
		// Ok to add Source.
		proposal.addSource(source);
	    }
	    
	    
	    // Save the bally Proposal now.
	    try {
		OSS_Utilities.storeProposal(proposal);
	    } catch (IOException ix) {
		logger.log(1, "ADD_SOURCE_Impl", id, "exec",
			   "Proposal ["+proposalPath.toString()+
			   "] Unable to Store: "+ix);
		return error(TRANSACTION.DATABASE_UPDATE_ERROR, 
			     "Proposal ["+proposalPath.toString()+
			     "] Unable to Store: "+ix);
	    }
	    
	    ADD_SOURCE_DONE done = new ADD_SOURCE_DONE(id); 
	    done.setSuccessful(true);
	    return done;
	    
	} finally { 
	    t.commit();
	}
    }
    
}

/** $Log: ADD_SOURCEImpl.java,v $
/** Revision 1.1  2006/11/27 08:45:00  snf
/** Initial revision
/**
/** Revision 1.1  2006/11/27 08:37:05  snf
/** Initial revision
/** */
